/*
	board.h		Game Board Operations
	Copyright (c) 2000-2004, 2006, 2010 Kriang Lerdsuwanakij
	email:		lerdsuwa@users.sourceforge.net

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#ifndef BOARD_H
#define BOARD_H

#include "config.h"

// Board squares
#define EMPTY	0
#define BLACK	1
#define WHITE	-1

// Total number of moves
#define NUM_MOVE	60

// Directions
#define NUM_DIR		8
#define DIR_START	0
#define DIR_END		7

// Impossible score to signal position evaluation
#define INVALID_SCORE	1000
#define MAX_SCORE	999
#define MIN_SCORE	-999

// Impossible position to signal a pass
#define POS_PASS 64
// Impossible position
#define POS_INVALID 65


// Board data types
typedef signed char piece_type;
typedef piece_type byte_board_type[64];

extern byte_board_type board_begin;

// x, y are 0-based.  Returns position in the 64-element array
inline int xy_to_pos(int x, int y)
{
	return y * 8 + x;
}

inline int pos_to_x(int pos)
{
	return pos % 8;
}

inline int pos_to_y(int pos)
{
	return pos / 8;
}

struct byte_board_info {
	private:
		char		move;
	public:
		byte_board_type	board;
		int		hash;
		byte_board_info();
		byte_board_info(const byte_board_type *board_init);

		byte_board_info& operator=(const byte_board_type *board_init);
		byte_board_info& operator=(const byte_board_info &src);

		void set_pos(int color, int pos);

		bool is_empty(int x, int y) const {
			return board[xy_to_pos(x, y)] == EMPTY;
		}

		bool is_empty(int pos) const {
			return board[pos] == EMPTY;
		}

		int	get_num_move() const { return move; }

		bool	can_play_nocheck(int color, int pos) const;
		bool	can_play(int color, int pos) const {
					// This seems to be get the
					// fastest code
			if (!is_empty(pos))
				return false;
			return can_play_nocheck(color, pos);
		}

		bool	can_play_nocheck(int color, int pos,
					 int dir_count[NUM_DIR]) const;
		bool	can_play(int color, int pos, 
				 int dir_count[NUM_DIR]) const {
					// This seems to be get the
					// fastest code
			if (!is_empty(pos))
				return false;
			return can_play_nocheck(color, pos, dir_count);
		}

		bool	can_play(int color) const;
		bool	can_play() const {
			return can_play(BLACK) || can_play(WHITE);
		}

		void	place_piece(int color, int pos);
		void	place_piece(int color, int pos, int dir_count[NUM_DIR]);

		int	board_diff_score() const;
		int	board_black_score() const;
		int	board_white_score() const;
};

bool operator==(const byte_board_info &board1, const byte_board_info &board2);

inline void adjust_score(int &black_score, int &white_score)
{
	if (black_score + white_score < 64) {
		if (black_score > white_score)
			black_score = 64 - white_score;
		else if (black_score < white_score)
			white_score = 64 - black_score;
		else {
			// FIXME: Get the scoring right
                }
	}
}

// Switch BLACK <-> WHITE
inline int	switch_color(int color) { return -color; }

#endif /* BOARD_H */
